/////////////////////////////////////////////////////////////////////////////
// Name:        tts.h
// Purpose:     Text to speech classes for wxWidgets
// Author:      Julian Smart
// Modified by: 
// Created:     2009-02-10
// RCS-ID:      
// Copyright:   (c) Julian Smart
// Licence:     New BSD License
/////////////////////////////////////////////////////////////////////////////

#ifndef _WX_TTS_
#define _WX_TTS_

/*
 * Includes
 */

#include "tts/tts_property.h"

/*
 * Styles and types
 */

// Input formats. "Native" means - don't convert the text, pass directly
// to the engine. For example, MS SAPI XML.
// Consider adding "Auto" value.
#define wxTTS_PROP_INPUT_FORMAT_TEXT            wxString(wxT("Text"))
#define wxTTS_PROP_INPUT_FORMAT_HTML            wxString(wxT("HTML"))
#define wxTTS_PROP_INPUT_FORMAT_SSML            wxString(wxT("SSML"))
#define wxTTS_PROP_INPUT_FORMAT_NATIVE          wxString(wxT("Native"))

// Properties
#define wxTTS_PROP_SPEED                        wxT("Speed")
#define wxTTS_PROP_PITCH                        wxT("Pitch")
#define wxTTS_PROP_VOLUME                       wxT("Volume")
#define wxTTS_PROP_VOICE                        wxT("Voice")
#define wxTTS_PROP_VOICE_VARIANT                wxT("Voice variant")
#define wxTTS_PROP_PROGRAM_LOCATION             wxT("Program location")
#define wxTTS_PROP_DATA_LOCATION                wxT("Data location")
#define wxTTS_PROP_INPUT_FORMAT                 wxT("Input format")
#define wxTTS_PROP_PRIORITY                     wxT("Priority")

// Pass text unchanged to engine, apart from word substitutions
#define wxTTS_PROP_NO_SUBSTITUTIONS             wxT("No pronunciation substitutions")
#define wxTTS_PROP_SIMPLIFY_PUNCTUATION         wxT("Simplify punctuation")
#define wxTTS_PROP_TEXT_ENCODING                wxT("Text encoding")
#define wxTTS_PROP_ENGINE_WEBSITE               wxT("Web site")

// Capabilities
typedef enum {
    wxTTS_CAP_PROGRAM_LOCATION = 1,
    wxTTS_CAP_DATA_LOCATION,
    wxTTS_CAP_WRITE_WAVE_FILE,
    wxTTS_CAP_SPEAK_HTML,
    wxTTS_CAP_VOICE,
    wxTTS_CAP_VOICE_VARIATIONS,
    wxTTS_CAP_PITCH,
    wxTTS_CAP_SPEED,
    wxTTS_CAP_VOLUME,
    wxTTS_CAP_SSML,
    wxTTS_CAP_PAUSE,
    wxTTS_CAP_SKIP
} wxTTSCapability;

typedef enum
{
    wxTTS_NATIVE,
    wxTTS_PERCENT
} wxTTSQuantityType;

// Skip types
typedef enum
{
    wxTTS_SkipSentence,
    wxTTS_SkipParagraph
} wxTTSSkipType;

// Priority types
typedef enum
{
    wxTTS_Normal = 0,
    wxTTS_Alert = 1,
    wxTTS_Over = 2
};

// Speak options
#define wxTTS_SPEAK_ASYNC       0x01
#define wxTTS_SPEAK_SYNC        0x02
#define wxTTS_SPEAK_SYNC_YIELD  0x04

// Speech defaults
#define wxTTS_SPEED_DEFAULT_PERCENT  50
#define wxTTS_PITCH_DEFAULT_PERCENT  50
#define wxTTS_VOLUME_DEFAULT_PERCENT 50

/*
 * Forward declarations
 */

class wxTTSHandler;

/**
    @class wxTextToSpeech
    
    A class for driving alternate speech engines.

    @category{tts}
 */

class wxTTSTransformer;

class wxTextToSpeech: public wxEvtHandler
{    
    DECLARE_DYNAMIC_CLASS( wxTextToSpeech )

public:
// Constructors

    wxTextToSpeech();
    ~wxTextToSpeech();

// Operations

    /// Member initialisation
    void Init();

    /// Speak the text
    virtual bool Speak(const wxString& text, int options = wxTTS_SPEAK_ASYNC);

    /// Speak the file
    virtual bool SpeakFile(const wxString& filename, int options = wxTTS_SPEAK_ASYNC, const wxString& waveFilename = wxEmptyString);

    /// Is it speaking (possibly paused)?
    virtual bool IsSpeaking() const;

    /// Is it playing (speaking and not paused)?
    virtual bool IsPlaying() const { return IsSpeaking() && !IsPaused(); }

    /// Stop speaking
    virtual bool Stop();

    /// Pause
    virtual bool Pause();

    /// Resume
    virtual bool Resume();

    /// Is it paused?
    virtual bool IsPaused() const;

    /// Can we pause right now?
    virtual bool CanPause() const;

    /// Skip forward or backward the given number of items. A positive value skips forward,
    /// and a negative value skips back. A value of zero skips to the start of the item.
    /// itemType may be ignored by some or all engines.
    virtual bool Skip(int toSkip, wxTTSSkipType itemType = wxTTS_SkipSentence);

    /// Can we skip right now?
    virtual bool CanSkip() const;

    /// Does this handler have the specified capability?
    virtual bool HasCapability(wxTTSCapability capability) const;

    /// Set a property
    void SetProperty(const wxTTSProperty& property);
    void SetProperty(const wxString& name, const wxString& value);
    void SetProperty(const wxString& name, const wxString& value, const wxArrayString& choices);
    void SetProperty(const wxString& name, long value);
    void SetProperty(const wxString& name, int value);
    void SetProperty(const wxString& name, bool value);
    void SetProperty(const wxVariant& value);

    /// Get a property
    wxTTSProperty GetProperty(const wxString& name) const;

    /// Get a property value variant
    wxVariant GetPropertyValue(const wxString& name) const;

    /// Get a string property value
    wxString GetPropertyString(const wxString& name) const;

    /// Get a long property value
    long GetPropertyLong(const wxString& name) const;

    /// Get a double property value
    double GetPropertyDouble(const wxString& name) const;

    /// Get a bool property value
    long GetPropertyBool(const wxString& name) const;

    /// Does this property exist?
    bool HasProperty(const wxString& name) const;

    /// Get current properties - doesn't necessarily mean they're all supported
    wxArrayString EnumerateProperties() const;

    /// Get property count
    int GetPropertyCount() const;

    /// Get property
    wxTTSProperty GetProperty(size_t i) const;

    /// Set the pronunciation table
    wxTTSTransformer* GetTransformer() const { return m_transformer; }

    /// Get the pronunciation table
    void SetTransformer(wxTTSTransformer* transformer) { m_transformer = transformer; }

    /// Set the program location
    void SetProgramLocation(const wxString& location);

    /// Get the program location
    wxString GetProgramLocation() const;

    /// Set the program location
    void SetDataLocation(const wxString& location);

    /// Get the program location
    wxString GetDataLocation() const;

    /// Set the voice
    void SetVoice(const wxString& voice);

    /// Get the voice
    wxString GetVoice() const;

    /// Get the default voice
    wxString GetDefaultVoice() const;

    /// Set the voice variant
    void SetVoiceVariant(const wxString& variant);

    /// Get the voice variant
    wxString GetVoiceVariant() const;

    /// Get the default voice variant
    wxString GetDefaultVoiceVariant() const;

    /// Can these two voices be used together? Pass an empty string to the voice parameters
    /// to find out whether the engine in general supports simultaneous voices. Pass voice names
    /// to find out if these voices can be used simultaneously, when using the given engine.
    /// The voice names can be the same.
    /// The reason why we can't just ask whether one voice is compatible with itself, is that the
    /// same engine may provide several different voices, so we have to look for similarities in the voice names.
    bool VoicesAreCompatible(const wxString& engine, const wxString& voice1, const wxString& voice2) const;
    bool VoicesAreCompatible(const wxString& voice1, const wxString& voice2) const;

    /// Set the speed
    void SetSpeed(int speed, wxTTSQuantityType quantity = wxTTS_NATIVE);

    /// Get the speed
    int GetSpeed(wxTTSQuantityType quantity = wxTTS_NATIVE) const;

    /// Set the volume
    void SetVolume(int vol, wxTTSQuantityType quantity = wxTTS_NATIVE);

    /// Get the volume
    int GetVolume(wxTTSQuantityType quantity = wxTTS_NATIVE) const;

    /// Set the pitch
    void SetPitch(int pitch, wxTTSQuantityType quantity = wxTTS_NATIVE);

    /// Get the pitch
    int GetPitch(wxTTSQuantityType quantity = wxTTS_NATIVE) const;

    /// Set the priority. 0 (wxTTS_Normal) is normal priority, 1 (wxTTS_Alert) is alert priority,
    /// and 2 (wxTTS_Over) is over priority, which mixes audio with other audio on the system.
    /// Using wxTTS_Over can cause crashes for engines that are not coded for re-entrancy.
    void SetPriority(int priority);

    /// Get the priority
    int GetPriority() const;

    /// Set the error code
    void SetErrorCode(int errorCode) { m_errorCode = errorCode; }

    /// Get the error code
    int GetErrorCode() const { return m_errorCode; }

    /// Get a list of the available voices
    wxArrayString GetAvailableVoices() const;

    /// Get a list of the available voice variants
    wxArrayString GetAvailableVoiceVariants() const;

    /// Get a list of the available engine ids
    wxArrayString GetEngineIds() const;

    /// Get a list of the available engine display names
    wxArrayString GetEngineDisplayNames() const;

    /// Get a list of the available engine descriptions
    wxArrayString GetEngineDescriptions() const;

    /// Get current handler
    wxTTSHandler* GetCurrentHandler() const { return m_currentHandler; }
    
    /// Set current handler
    void SetCurrentHandler(wxTTSHandler* handler) { m_currentHandler = handler; }

    /// Add handler
    bool AddHandler(wxTTSHandler* handler);

    /// Find handler by id
    wxTTSHandler* FindHandler(const wxString& name) const;

    /// Get handler ccount
    int GetHandlerCount() const { return m_handlers.GetCount(); }

    /// Get handler
    wxTTSHandler* GetHandler(size_t i) const;

    /// Remove all handlers, uninitializing each one
    void ClearHandlers();

    /// Set current engine by id
    bool SetEngine(const wxString& id);

    /// Get current engine by id
    wxString GetEngine() const;

    /// For when the handler is using an external command,
    /// deal with input from command
    bool ProcessInput();

    /// Get last command, if using external command
    wxString GetLastCommand() const;

    /// Append paths without duplicating separator
    static wxString AppendPaths(const wxString& p1, const wxString& p2, const wxString& sep = wxFILE_SEP_PATH);

    /// Intelligent strip extension: don't strip before a separator,
    /// and don't strip if the 'extension' is different from the passed extension
    /// that we expect - can be comma-separated list.
    static bool StripExtension(wxString& path, const wxString& validExtensions = wxEmptyString);

    /// Find the encoding of an HTML file
    static wxString FindHtmlEncoding(const wxString& filename);

    /// Find the encoding of an XML file
    static wxString FindXmlEncoding(const wxString& filename);

    /// Is this an XML string?
    static bool IsXmlString(const wxString& text);

    /// Is this an XML file?
    static bool IsXmlFile(const wxString& filename);

protected:
    int                 m_errorCode;
    wxList              m_handlers;
    wxTTSHandler*       m_currentHandler;
    wxTTSTransformer*   m_transformer;
};

WX_DECLARE_STRING_HASH_MAP(wxString*, wxTTSStringHashMap);

// Do word substitution
#define wxTTS_TRANSFORM_OPTIONS_WORD_SUBSTITUTION       0x0001

// Remove title element to stop duplication
#define wxTTS_TRANSFORM_OPTIONS_REMOVE_TITLE_ELEMENT    0x0002

// Replace Unicode punctuation with simpler punctuation
#define wxTTS_TRANSFORM_OPTIONS_SIMPLIFY_PUNCTUATION    0x0004

// Remove XML preamble (xml, doctype)
#define wxTTS_TRANSFORM_OPTIONS_REMOVE_XML_PREAMBLE     0x0008

// Pass to the engine unchanged, except for word substitutions
#define wxTTS_TRANSFORM_PASS_RAW_TEXT                   0x0010

// Convert HTML to text
#define wxTTS_TRANSFORM_HTML_TO_TEXT                    0x0020

// Convert HTML to SAPI XML
#define wxTTS_TRANSFORM_HTML_TO_SAPI_XML                0x0040

// Convert HTML to SSML
#define wxTTS_TRANSFORM_HTML_TO_SSML                    0x0080

// Convert text to SAPI XML
#define wxTTS_TRANSFORM_TEXT_TO_SAPI_XML                0x0100

// Convert text to SSML
#define wxTTS_TRANSFORM_TEXT_TO_SSML                    0x0200

// Speak HTML heading levels
#define wxTTS_TRANSFORM_SPEAK_HEADINGS                  0x0400

// Speak HTML list numbers
#define wxTTS_TRANSFORM_SPEAK_ORDERED_LIST              0x0800

/**
    @class wxTTSTransformer
    
    A class for applying various transformations to text before it is sent to the
    speech engine.

    @category{tts}
 */

class wxTTSTransformer
{    
public:
    // Constructors

    wxTTSTransformer();
    virtual ~wxTTSTransformer();

    /// Add a string
    void AddString(const wxString& word, const wxString& replacement);

    /// Insert string before this one
    void InsertString(const wxString& word, const wxString& replacement, int pos);

    /// Remove a string
    void RemoveString(const wxString& word);
    void RemoveString(size_t i);

    /// Get a string
    wxString GetString(const wxString& word);

    /// Has string
    bool HasString(const wxString& word);

    /// Clear
    virtual void Clear();

    /// Index the strings
    virtual void Index();

    /// Do transformations in a text string
    virtual bool TransformString(const wxString& input, wxString& output, int options = wxTTS_TRANSFORM_OPTIONS_WORD_SUBSTITUTION);

    /// Do transformations in a text file
    virtual bool TransformFile(const wxString& filename, const wxString& newFilename, int options = wxTTS_TRANSFORM_OPTIONS_WORD_SUBSTITUTION);

    /// Save the table to a file
    virtual bool SaveFile(const wxString& filename);

    /// Load the table from a file
    virtual bool LoadFile(const wxString& filename);

    /// Convert from one format to another, e.g. text to XML, or HTML to text
    virtual bool ConvertFormat(const wxString& filename, wxOutputStream& rawStream, wxTextOutputStream& stream, int options);

    /// Convert HTML to text, SAPI XML or SSML
    virtual bool ConvertHTMLToText(const wxString& filename, wxOutputStream& rawStream, wxTextOutputStream& stream, int options);

    /// Convert plain text to SAPI XML or SSML
    virtual bool ConvertTextToXML(const wxString& filename, wxOutputStream& rawStream, wxTextOutputStream& stream, int options);

    /// Get words
    wxArrayString& GetStrings() { return m_strings; }
    wxArrayString& GetReplacements() { return m_replacements; }

    /// Are their strings?
    bool HasStrings() const { return m_strings.GetCount() > 0; }

    /// Set dirty flag - if true, needs indexing
    void SetDirty(bool dirty) { m_dirty = dirty; }
    bool GetDirty() const { return m_dirty; }

    /// Set modified flag - if true, needs saving
    void SetModified(bool mod = true) { m_modified = mod; }
    bool GetModified() const { return m_modified; }

    /// Set a summary of how to use the table, preferably in simplified HTML.
    void SetUsageDescription(const wxString& descr) { m_usageDescription = descr; }

    /// Get a summary of how to use the table, preferably in simplified HTML.
    wxString GetUsageDescription() const { return m_usageDescription; }

    /// Replace character with another character
    static bool ReplaceChar(wxString& str, const wxChar& ch1, const wxChar& ch2);

protected:

    wxArrayString       m_strings;
    wxArrayString       m_replacements;
    wxTTSStringHashMap  m_hashMap;
    bool                m_dirty;
    bool                m_modified;
    wxString            m_usageDescription;
};

/**
    @class wxTTSHandler
    
    A base class for implementing a driver for a particular speech engine.

    @category{tts}
 */

class wxTTSHandler: public wxEvtHandler
{    
    DECLARE_CLASS( wxTTSHandler )

public:
// Constructors

    wxTTSHandler(const wxString& id = wxEmptyString, const wxString& displayName = wxEmptyString);
    ~wxTTSHandler();

// Operations

    /// Initialize the engine. Can call multiple times.
    virtual bool Initialize() { return true; }

    /// Clean up the engine. Can call multiple times.
    virtual bool Uninitialize() { return true; }

    /// Speak the text
    virtual bool Speak(const wxString& text, int options = wxTTS_SPEAK_ASYNC) = 0;

    /// Speak the file
    virtual bool SpeakFile(const wxString& filename, int options = wxTTS_SPEAK_ASYNC, const wxString& waveFilename = wxEmptyString) = 0;

    /// Is it speaking?
    virtual bool IsSpeaking() const = 0;

    /// Is it speaking?
    virtual bool IsPaused() const { return false; }

    /// Stop speaking
    virtual bool Stop() = 0;

    /// Pause
    virtual bool Pause() { return false; }

    /// Pause
    virtual bool Resume() { return false; }

    /// Skip forward or backward the given number of items. A positive value skips forward,
    /// and a negative value skips back. A value of zero skips to the start of the item.
    /// itemType may be ignored by some or all engines.
    virtual bool Skip(int WXUNUSED(toSkip), wxTTSSkipType WXUNUSED(itemType) = wxTTS_SkipSentence) { return false; }

    /// Can we skip right now?
    virtual bool CanSkip() const { return false; }

    /// Does this handler have the specified capability?
    virtual bool HasCapability(wxTTSCapability capability) const = 0;

    /// Can these two voices be used together? Pass an empty string to the voice parameters
    /// to find out whether the engine in general supports simultaneous voices. Pass voice names
    /// to find out if these voices can be used simultaneously, when using the given engine.
    /// The voice names can be the same.
    virtual bool VoicesAreCompatible(const wxString& WXUNUSED(voice1), const wxString& WXUNUSED(voice2)) const { return true; }

    /// For when the handler is using an external command,
    /// deal with input from command
    virtual bool ProcessInput() { return true; }

    /// Get last command, if using external command
    virtual wxString GetLastCommand() const { return wxEmptyString; }

    /// Set a property
    virtual void SetProperty(const wxTTSProperty& property);
    virtual void SetProperty(const wxString& name, const wxString& value);
    virtual void SetProperty(const wxString& name, const wxString& value, const wxArrayString& choices);
    virtual void SetProperty(const wxString& name, long value);
    virtual void SetProperty(const wxString& name, int value);
    virtual void SetProperty(const wxString& name, bool value);
    virtual void SetProperty(const wxVariant& value);

    /// Get a property
    virtual wxTTSProperty GetProperty(const wxString& name) const;

    /// Get a property value variant
    virtual wxVariant GetPropertyValue(const wxString& name) const;

    /// Get a string property value
    virtual wxString GetPropertyString(const wxString& name) const;

    /// Get a long property value
    virtual long GetPropertyLong(const wxString& name) const;

    /// Get a double property value
    virtual double GetPropertyDouble(const wxString& name) const;

    /// Get a bool property value
    virtual long GetPropertyBool(const wxString& name) const;

    /// Does this property exist?
    virtual bool HasProperty(const wxString& name) const;

    /// Get current properties - doesn't necessarily mean they're all supported
    virtual wxArrayString EnumerateProperties() const;

    /// Get property count
    virtual int GetPropertyCount() const { return m_properties.GetCount(); }

    /// Get property
    virtual wxTTSProperty GetProperty(size_t i) const;

    /// Get properties
    virtual const wxTTSProperties& GetProperties() const { return m_properties; }
    virtual wxTTSProperties& GetProperties() { return m_properties; }

    /// Set/get the program location
    virtual void SetProgramLocation(const wxString& location) { SetProperty(wxTTS_PROP_PROGRAM_LOCATION, location); }
    virtual wxString GetProgramLocation() const { return GetPropertyString(wxTTS_PROP_PROGRAM_LOCATION); }

    /// Set/get the program location
    virtual void SetDataLocation(const wxString& location) { SetProperty(wxTTS_PROP_DATA_LOCATION, location); }
    virtual wxString GetDataLocation() const { return GetPropertyString(wxTTS_PROP_DATA_LOCATION); }

    /// Set/get the voice
    virtual void SetVoice(const wxString& voice) { SetProperty(wxTTS_PROP_VOICE, voice); }
    virtual wxString GetVoice() const { return GetPropertyString(wxTTS_PROP_VOICE); }

    /// Get the default voice
    virtual wxString GetDefaultVoice() const = 0;

    /// Get a list of the available voices
    virtual wxArrayString GetAvailableVoices() const = 0;

    /// Get a list of the available voice variants
    virtual wxArrayString GetAvailableVoiceVariants() const { return wxArrayString(); }

    /// Set/get the voice variant
    virtual void SetVoiceVariant(const wxString& variant) { SetProperty(wxTTS_PROP_VOICE_VARIANT, variant); }
    virtual wxString GetVoiceVariant() const { return GetPropertyString(wxTTS_PROP_VOICE_VARIANT); }

    /// Get the default voice variant
    virtual wxString GetDefaultVoiceVariant() const = 0;

    /// Set/get the speed
    virtual void SetSpeed(int speed, wxTTSQuantityType quantity = wxTTS_NATIVE);
    virtual int GetSpeed(wxTTSQuantityType quantity = wxTTS_NATIVE) const;
    virtual int GetMinSpeed() const = 0;
    virtual int GetMaxSpeed() const = 0;

    /// Set/get the volume
    virtual void SetVolume(int vol, wxTTSQuantityType quantity = wxTTS_NATIVE);
    virtual int GetVolume(wxTTSQuantityType quantity = wxTTS_NATIVE) const;
    virtual int GetMinVolume() const = 0;
    virtual int GetMaxVolume() const = 0;

    /// Set/get the pitch
    virtual void SetPitch(int pitch, wxTTSQuantityType quantity = wxTTS_NATIVE);
    virtual int GetPitch(wxTTSQuantityType quantity = wxTTS_NATIVE) const;
    virtual int GetMinPitch() const = 0;
    virtual int GetMaxPitch() const = 0;

    /// Set/get the error code
    void SetErrorCode(int errorCode) { m_errorCode = errorCode; }
    int GetErrorCode() const { return m_errorCode; }

    /// Set/get a pointer to the parent text to speech object
    void SetTextToSpeechObject(wxTextToSpeech* tts) { m_textToSpeech = tts; }
    wxTextToSpeech* GetTextToSpeechObject() const { return m_textToSpeech; }

    /// Set/get the handler id
    void SetId(const wxString& id) { m_id = id; }
    wxString GetId() const { return m_id; }

    /// Set/get the handler display name
    void SetDisplayName(const wxString& name) { m_displayName = name; }
    const wxString& GetDisplayName() const { return m_displayName; }

    /// Set/get the handler description
    void SetDescription(const wxString& descr) { m_description = descr; }
    const wxString& GetDescription() const { return m_description; }

    /// Member initialisation
    void Init();

    /// Set/get initialized status
    bool GetInitialized() const { return m_isInitialized; }
    void SetInitialized(bool init) { m_isInitialized = init; }

    /// Set/get speak options
    int GetOptions() const { return m_options; }
    void SetOptions(int options) { m_options = options; }

    /// Delete temporary file
    void DeleteTempFile();

    /// Helpers
    static int PercentToNativeValue(int value, int minValue, int maxValue);
    static int NativeValueToPercent(int value, int minValue, int maxValue);

    /// Create transformation options from handler's properties
    virtual int CreateTransformerOptions(int mandatoryOptions = 0) const;

    /// Do the transformation
    wxString DoTransformation(const wxString& originalFilename, int transformationFlags);

    /// Get pronunciation table
    wxTTSTransformer* GetTransformer() const;

protected:
    int                 m_errorCode;
    int                 m_options;
    wxString            m_tempFilename;     // Temp name when applying transformations
    wxString            m_id;               // The identifier for this handler
    wxString            m_displayName;      // Display name for this handler
    wxString            m_description;      // Description for this handler
    wxTextToSpeech*     m_textToSpeech;
    wxTTSProperties     m_properties;
    bool                m_isInitialized;
};

/**
    @class wxTTSSpeechSettingsInfo

    Stores global speech settings.
    
    @category{tts}
 */

class wxTTSSpeechSettingsInfo
{
public:
    wxTTSSpeechSettingsInfo() { Init(); }

    void Init()
    { m_speed = wxTTS_SPEED_DEFAULT_PERCENT; m_volume = wxTTS_VOLUME_DEFAULT_PERCENT;
      m_pitch = wxTTS_PITCH_DEFAULT_PERCENT; m_speech = NULL; m_testText = _("Testing text to speech settings."); }
    void Copy(const wxTTSSpeechSettingsInfo& info)
    { m_speech = info.m_speech; m_testText = info.m_testText;
      m_speed = info.m_speed; m_volume = info.m_volume; m_pitch = info.m_pitch; m_engine = info.m_engine; }
    void operator=(const wxTTSSpeechSettingsInfo& info) { Copy(info); }

    /// Apply the settings to the text to speech object
    bool ApplySettings();

    int                 m_speed, m_volume, m_pitch;
    wxString            m_engine, m_testText;
    wxTextToSpeech*     m_speech;
};

#endif
    // _WX_TTS_
